﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;


using System.Data;
using System.Xml;
using System.Xml.Linq;
using Tong;
using System.Text;
using System.IO;

/// <summary>
/// 創建人:Skybot
/// 創建日期:2009-10-10
/// 功能 DataTable 轉實體類 示例
/// 已知BUG 返回實體類沒有記錄會返回一個 空實體類對像
/// </summary>
public partial class _35newpart_動態匿名類型 : System.Web.UI.Page
{
    DataTable Mydt = new DataTable();


    Tong.TongUse TextData = new Tong.TongUse();

    DynamicCreateDataTableEntity DynamicRun動態DataTable实体类生成工具 = new DynamicCreateDataTableEntity();

    protected void Page_Load(object sender, EventArgs e)
    {
        Mydt = TextData.SqlataSet("select top 5000 * from [CX_NEWS]").Tables[0];


        DataTable MyDt = new DataTable();



        DynamicRun動態DataTable实体类生成工具.CodeDirectoryPath = @"E:\網站項目\Net项目试用\Xml\App_Code\DynamicCreateDataTableEntity\";



        Response.Write("<br/>生成類名:" +

            //完全限定文件名必须少于 260 个字符

        ///指定類名生成實體類名
        DynamicRun動態DataTable实体类生成工具.CreateEntityClassWithDataTable(Mydt, "CX_NEWSEntity")

        );

        //跟據字段名生成實體類名
        DynamicRun動態DataTable实体类生成工具.CreateEntityClassWithDataTable(Mydt);


        var Entitys = Mydt.ToEntityList<DynamicDataTableEntity.CX_NEWSEntity>();


        GridView1.DataSource = from p in Entitys select new { 
          序號=p.CX_NEWS_id,
          名字=p.CX_NEWS_Name,
          路徑=p.CX_NEWS_Pic_Url,
          
        };
        GridView1.DataBind();

   

    }




}

public class tempClass
{
    public Decimal CX_NEWS_Class_id
    {
        get;
        set;
    }
}


 

/// <summary>
/// 動態 n動態DataTable实体类生成工具
/// 初始化 當前要生成 cs  CS 文件的 目錄 
/// 默認為 D:\DynamicCreateDataTableEntity\
/// </summary>
public class DynamicCreateDataTableEntity
{
    #region 構造函數


    public DynamicCreateDataTableEntity()
    {

    }


    /// <summary>
    /// 構造函數
    /// </summary>
    /// <param name="codeDirectoryPath">要寫入文件的路徑</param>
    public DynamicCreateDataTableEntity(string codeDirectoryPath)
    {
        CodeDirectoryPath = codeDirectoryPath;
    }

    #endregion



    #region 公共屬性

    /// <summary>
    /// 初始化 當前要生成
    /// CS 文件的 目錄 
    /// 默認為 D:\DynamicCreateDataTableEntity\
    /// </summary>
    private string _codeDirectoryPath = @"D:\DynamicCreateDataTableEntity\";

    /// <summary>
    /// 初始化 當前要生成
    /// CS 文件的 目錄 
    /// 默認為 D:\DynamicRun\
    /// </summary>
    public string CodeDirectoryPath
    {
        get;
        set;
    }

    #endregion



    #region 外部可訪問的公共方法

    /// <summary>
    /// 返回 生成的 生成類的名稱
    /// </summary>
    /// <param name="myDt">傳入的DataTable</param>
    /// <returns>创建生成的类名</returns>
    public virtual string CreateEntityClassWithDataTable(DataTable myDt)
    {
        return CreateEntityClassWithDataTable(myDt, null);
    }


    /// <summary>
    /// 返回 生成的 生成類的名稱
    /// </summary>
    /// <param name="myDt">傳入的DataTable</param>
    /// <param name="CreateClassName">要创建生成的类名  如果同名文件存在將替換</param>
    /// <returns>创建生成的类名</returns>
    public virtual string CreateEntityClassWithDataTable(DataTable myDt, string CreateClassName)
    {
        if (myDt.Columns.Count <= 0)
        {
            throw new Exception("DataTable 不包括任何列");
        }

        //生成的類名
        string ClassName = "";

        //生成運行Code
        string TempCode = "";

        #region 跟據 傳入的參數 看看是不是 已經指定了創建類名

        ///如果 指定了 创建名 则创建指定的类名
        ///指定的類名
        if (CreateClassName != null)
        {
            TempCode = CreateCodes(myDt, CreateClassName, out ClassName);
        }
        else
        {
            //沒有指定名，自動創建類名
            TempCode = CreateCodes(myDt, out ClassName);
        }

        #endregion


        //得到一個新的字符串 生要生成的文件名
        string ClassFileName = new string(ClassName.ToCharArray());

        //新的文件名
        ClassFileName = CodeDirectoryPath + "/" + ClassFileName + ".cs";

        //創建不存在的目錄
        if (!Directory.Exists(CodeDirectoryPath))
        {
            Directory.CreateDirectory(CodeDirectoryPath);
        }


        //如果文件名長度超過 220 個字符
        if (ClassFileName.Length >= 220)
        {
            ClassFileName = ClassFileName.Substring(0, 220) + Guid.NewGuid().ToString() + ".cs";
        }

        ///如果不在此類型
        if (!IsClassExists(ClassName))
        {
            //寫入新文件
            System.IO.StreamWriter Sw = new System.IO.StreamWriter(ClassFileName, false, System.Text.Encoding.Default);
            Sw.Write(TempCode);
            Sw.Flush();
            Sw.Close();
            Sw.Dispose();


            //打印記錄
            System.Diagnostics.Debug.WriteLine("DynamicRun 生成 文件 " + CodeDirectoryPath + "/" + ClassName + ".cs");
        }

        return ClassName;
    }

    #endregion


    #region 子類可見的方法

    /// <summary>
    /// 傳入一個類名 看看當前類是不是存在於
    /// 當前的命名空間中
    /// </summary>
    /// <param name="ClassName">類名</param>
    /// <returns>返回 bool 存在 true,不存在 False</returns>
    protected virtual bool IsClassExists(string ClassName)
    {
        string[] Files = System.IO.Directory.GetFiles(CodeDirectoryPath);

        ///得到所有文件
        foreach (string FileFullName in Files)
        {
            //得到第一行的內容
            //示例
            //  ///ClassName:TableCX_NEWS_idCX_NEWS_NameCX_NEWS_Class_idCX_NEWS_CreaterCX_NEWS_FromCX_NEWS_TopCX_NEWS_PicCX_NEWS_Pic_UrlCX_NEWS_PublicTimeCX_NEWS_ContCX_NEWS_SortCx_keyWord_NameCX_NEWS_TitleCX_NEWS_KeyWordsCX_NEWS_DescriptionCX_NEWS_Class_Edit 

            string lineContent = System.IO.File.ReadAllLines(FileFullName)[0];

            //如果已經存在類型
            if ("///ClassName:" + ClassName.Trim() == lineContent.Trim())
            {
                return true;
                //System.Web.HttpContext.Current.Response.Write(lineContent);
            }

        }
        return false;
    }


    /// <summary>
    /// 傳入DataTable 生成 Codes
    /// </summary>
    /// <param name="myDt">傳入的DataTable</param>
    /// <param name="ClassName">生成類的名稱</param>
    /// <returns>返回生成的 Cs 文件代码</returns>
    protected virtual string CreateCodes(DataTable myDt, out string ClassName)
    {
        return CreateCodes(myDt, null, out ClassName);

    }



    /// <summary>
    /// 傳入DataTable 生成 Codes
    /// </summary>
    /// <param name="myDt">傳入的DataTable</param>
    /// <param name="CreateClassName">要生成的類名</param>
    /// <param name="ClassName">生成類的名稱</param>
    /// <returns>返回生成的 Cs 文件代码</returns>
    protected virtual string CreateCodes(DataTable myDt, string CreateClassName, out string ClassName)
    {
        /// <summary>
        /// 代碼 Code
        /// </summary>
        StringBuilder CodeStrBuilder = new StringBuilder();

        ///包含的字段
        string Fields = "";

        //默認類名
        ClassName = myDt.TableName;

        ///輸出列
        foreach (System.Data.DataColumn column in myDt.Columns)
        {
            //得到列名
            ClassName += column.ColumnName;
        }

        Fields = ClassName;

        #region 处理当前要得到生成的 ClassName

        ///如果 指定了 创建名 则创建指定的类名
        if (CreateClassName != null)
        {
            ClassName = CreateClassName;
        }

        #endregion

        //得到當前的文件名
        CodeStrBuilder.AppendFormat("///ClassName:{0}", ClassName);
        CodeStrBuilder.AppendLine(" ");
        CodeStrBuilder.AppendLine("namespace DynamicDataTableEntity");
        CodeStrBuilder.AppendLine("{");
        CodeStrBuilder.AppendLine("        /// <summary>");
        CodeStrBuilder.AppendFormat("        /// 創建日期 {0}  ", DateTime.Now);
        CodeStrBuilder.AppendLine(" ");
        CodeStrBuilder.AppendFormat("        /// DataTable 包含字段 {0}  ", Fields);
        CodeStrBuilder.AppendLine(" ");
        CodeStrBuilder.AppendFormat("        /// 操作數據實體類");
        CodeStrBuilder.AppendLine("");
        CodeStrBuilder.AppendLine("        /// </summary>");
        CodeStrBuilder.AppendLine(" ");
        CodeStrBuilder.AppendFormat("    public class {0}", ClassName);
        CodeStrBuilder.AppendLine("");
        CodeStrBuilder.AppendLine("    {");

        ///輸出列
        foreach (System.Data.DataColumn column in myDt.Columns)
        {
            //資料類型
            //Response.Write(column.DataType.ToString() + "<br/>");

            //获取或设置存储在列中的数据的类型。 
            //column.DataType = System.Type.GetType("System.Decimal");

            //获取或设置一个值，该值指示对于属于该表的行，此列中是否允许空值。 
            //column.AllowDBNull = false;

            //获取或设置 DataColumnCollection 中的列的名称
            //column.ColumnName = "Price";

            //在创建新行时获取或设置列的默认值
            //column.DefaultValue = 25;


            CodeStrBuilder.AppendLine("        /// <summary>");
            CodeStrBuilder.AppendFormat("        /// {0}", column.ColumnName + column.Container);
            CodeStrBuilder.AppendLine("");
            CodeStrBuilder.AppendLine("        /// </summary>");
            CodeStrBuilder.AppendFormat("        public {0} {1}", column.DataType.ToString(), column.ColumnName);
            CodeStrBuilder.AppendLine("");
            CodeStrBuilder.AppendLine("        {");
            CodeStrBuilder.AppendLine("            get;");
            CodeStrBuilder.AppendLine("            set;");
            CodeStrBuilder.AppendLine("");
            CodeStrBuilder.AppendLine("        }");

        }



        CodeStrBuilder.AppendLine("    }");
        CodeStrBuilder.AppendLine("}");

        return CodeStrBuilder.ToString();
    }


    #endregion

}



/// <summary>
/// DataTable 轉換成實體的對像
/// </summary>
public static class DataTableToEntitys 
{



    /// <summary>
    /// 把对应表的数据转成对象
    /// </summary>
    /// <param name="myDs">传入的DataTable</param>
    /// <returns>返回資料實體</returns>
    public  static T[] ToEntityArray<T>(this DataTable Mydt) where T : new()
    {
        /// <summary>
        /// 當前對類型實例
        /// </summary>
        T myt = new T();


        //定义一个方法用于显示数据 类型的集合
        T[] p = new T[1];
        if (Mydt.Rows.Count == 0)
        {
            p[0] = myt;
        }
        else
        {
            p = new T[Mydt.Rows.Count];
        }


        for (int i = 0; i < Mydt.Rows.Count; i++)
        {

            object Mydato = Activator.CreateInstance(myt.GetType());//实例化新对像

            #region 实现转换的方法

            ///开始使用方法传入属性值
            foreach (System.Reflection.PropertyInfo Proper in myt.GetType().GetProperties())
            {
                Mydato.GetType().GetProperty(Proper.Name).SetValue(Mydato,
                    //传值
                    //  Mydt.Rows[i][Proper.Name].GetType().ToString() 得到当前的类型
                    // Myt.GetType().GetProperty(Proper.Name).GetValue(Myt, null);//返回默认值
                    // Mydt.Rows[i][Proper.Name] 得到当前的值
                    Mydt.Rows[i][Proper.Name].GetType().ToString() == System.DBNull.Value.GetType().ToString() ? myt.GetType().GetProperty(Proper.Name).GetValue(myt, null) : Mydt.Rows[i][Proper.Name]
                    , null);

            }

            #endregion
            p[i] = (T)Mydato;


        }


        return p;
    }

    /// <summary>
    /// 把对应表的数据转成对象
    /// </summary>
    /// <param name="myDs">传入的DataTable</param>
    /// <returns>返回資料實體</returns>
    public   static List<T> ToEntityList<T>(this DataTable Mydt) where T : new()
    {
        return ToEntityArray<T>(Mydt).ToList();
    }

    /// <summary>
    /// 把对应表的数据转成对象
    /// </summary>
    /// <param name="myDs">传入的DataTable</param>
    /// <returns>返回資料實體</returns>
    public static List<T> ToEntityList<T>(this DataTable Mydt,bool boolValue) where T : new()
    {
         /// <summary>
        /// 當前對類型實例
        /// </summary>
        T myt = new T();

        ///定義一個字段實體類
        ///用於保存 DataTable中和 實體類中共同有的 交集字段部分
       List<System.Collections.DictionaryEntry> Dirctions = new List<System.Collections.DictionaryEntry>(); 


        //定义一个方法用于显示数据 类型的集合
        List<T> EntitiesTypeList = new List<T>();


        #region 開始得到交集部分

         ///得到屬性集合
         System.Reflection.PropertyInfo[] propertyInfos =     myt.GetType().GetProperties();

        ///得到所有的DataTable字段集合
         DataColumnCollection Clounms = Mydt.Columns;


        ///如果屬性的個數多
        if(propertyInfos.Length>Clounms.Count)
        {
            foreach (System.Reflection.PropertyInfo Proper in myt.GetType().GetProperties())
            { 
                
            }
        }
        
        ///如果DataTable的屬性 多
        if(Clounms.Count>propertyInfos.Length)
        {
            
        }


        ///如果相等
        if(Clounms.Count == propertyInfos.Length)
        {
            
        }




	    #endregion


        //for (int i = 0; i < Mydt.Rows.Count; i++)
        //{

        //    object Mydato = Activator.CreateInstance(myt.GetType());//实例化新对像

        //    #region 实现转换的方法

        //    ///开始使用方法传入属性值
        //    foreach (System.Reflection.PropertyInfo Proper in myt.GetType().GetProperties())
        //    {
        //        Mydato.GetType().GetProperty(Proper.Name).SetValue(Mydato,
        //            //传值
        //            //  Mydt.Rows[i][Proper.Name].GetType().ToString() 得到当前的类型
        //            // Myt.GetType().GetProperty(Proper.Name).GetValue(Myt, null);//返回默认值
        //            // Mydt.Rows[i][Proper.Name] 得到当前的值
        //            Mydt.Rows[i][Proper.Name].GetType().ToString() == System.DBNull.Value.GetType().ToString() ? myt.GetType().GetProperty(Proper.Name).GetValue(myt, null) : Mydt.Rows[i][Proper.Name]
        //            , null);

        //    }

        //    #endregion


        //    p[i] = (T)Mydato;


            return ToEntityArray<T>(Mydt).ToList();

    }
}
